#include "TestgRpcClient.h"


GreeterSynClient::GreeterSynClient(std::shared_ptr<Channel> channel)
{
    stub_ = Greeter::NewStub(channel);
}

//服务端同步类方法的函数实现.
std::string GreeterSynClient::SayHello(const std::string& user)
{
    // Data we are sending to the server.
    HelloRequest request;
    request.set_name(user);

    // Container for the data we expect from the server.
    HelloReply reply;

    // Context for the client. It could be used to convey extra information to
    // the server and/or tweak certain RPC behaviors.
    ClientContext context;

    // The actual RPC.
    Status status = stub_->SayHello(&context, request, &reply);

    // Act upon its status.
    if (status.ok()) {
      return reply.message();
    } else {
      std::cout << status.error_code() << ": " << status.error_message()
                << std::endl;
      return "RPC failed";
    }
}

//explicit
GreeterAsynClient::GreeterAsynClient(std::shared_ptr<Channel> channel)
{
    stub_ = Greeter::NewStub(channel);
}

//异步调用实现
std::string GreeterAsynClient::SayHello(const std::string& user)
{
    // Data we are sending to the server.
    HelloRequest request;
    request.set_name(user);

    // Container for the data we expect from the server.
    HelloReply reply;

    // Context for the client. It could be used to convey extra information to
    // the server and/or tweak certain RPC behaviors.
    ClientContext context;

    // The producer-consumer queue we use to communicate asynchronously with the
    // gRPC runtime.
    CompletionQueue cq;

    // Storage for the status of the RPC upon completion.
    Status status;

    std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
        stub_->PrepareAsyncSayHello(&context, request, &cq));

    // StartCall initiates the RPC call
    rpc->StartCall();

    rpc->Finish(&reply, &status, (void*)1);
    void* got_tag;
    bool ok = false;

    GPR_ASSERT(cq.Next(&got_tag, &ok));

    GPR_ASSERT(got_tag == (void*)1);
    GPR_ASSERT(ok);

    // Act upon the status of the actual RPC.
    if (status.ok()) {
      return reply.message();
    } else {
      return "RPC failed";
    }
}

#if 1
//异步调用实现方法二，单独的线程处理.
//explicit
GreeterAsynClient2::GreeterAsynClient2(std::shared_ptr<Channel> channel)
{
    stub_ = Greeter::NewStub(channel);
}

void GreeterAsynClient2::SayHello(const std::string& user)
{
    //发送给服务端的数据
    HelloRequest request;
    request.set_name(user);

    //保存在rpc数据的回调对象
    AsyncClientCall* call = new AsyncClientCall;

    // stub_->PrepareAsyncSayHello() creates an RPC object, returning
    // an instance to store in "call" but does not actually start the RPC
    // Because we are using the asynchronous API, we need to hold on to
    // the "call" instance in order to get updates on the ongoing RPC.
    call->response_reader =
        stub_->PrepareAsyncSayHello(&call->context, request, &cq_);

    // StartCall initiates the RPC call
    call->response_reader->StartCall();

    // Request that, upon completion of the RPC, "reply" be updated with the
    // server's response; "status" with the indication of whether the operation
    // was successful. Tag the request with the memory address of the call
    // object.
    call->response_reader->Finish(&call->reply, &call->status, (void*)call);
}

void GreeterAsynClient2::AsyncCompleteRpc(void)
{
    void* got_tag;
    bool ok = false;

    // Block until the next result is available in the completion queue "cq".
    while (cq_.Next(&got_tag, &ok)) {
      // The tag in this example is the memory location of the call object
      AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag);

      // Verify that the request was completed successfully. Note that "ok"
      // corresponds solely to the request for updates introduced by Finish().
      GPR_ASSERT(ok);

      if (call->status.ok())
        std::cout << "Greeter received: " << call->reply.message() << std::endl;
      else
        std::cout << "RPC failed" << std::endl;

      // Once we're complete, deallocate the call object.
      delete call;
    }
}

#endif

TestGRPCClient * TestGRPCClient::m_pInstance = NULL;
TestGRPCClient * TestGRPCClient::Instance()
{
    if(m_pInstance == NULL) m_pInstance = new TestGRPCClient();
    return m_pInstance;
}

TestGRPCClient::TestGRPCClient()
{
    m_pInstance = 0;
    Syngreeter = 0;
    Asyngreeter = 0;
    Asyngreeter2 = 0;
}
TestGRPCClient::~TestGRPCClient()
{
    delete m_pInstance;
    m_pInstance = 0;
    delete Syngreeter;
    Syngreeter = 0;
    delete Asyngreeter;
    Asyngreeter = 0;
    delete Asyngreeter2;
    Asyngreeter2 = 0;
}

//TestgRPC同步服务端的调用，传递获取的GRPC的接口和框架处理后的端口IP信息
void OSGI_API TestGRPCClient::TestgRPCSynClientRun(std::string server_address)
{
    //创建通道
    Syngreeter = new GreeterSynClient(grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials()));

    //处理业务，设置发送信息
    std::string user("world Syn !!!");

    //业务逻辑，调用接口
    for (int i = 0; i < 15; i++) {
      std::string reply = Syngreeter->SayHello(user);
      std::cout << "Syn Greeter received: " << reply << "第" << i << "次回复" << std::endl;
    }

}

void OSGI_API TestGRPCClient::TestgRPCAsynClientRun(std::string server_address)
{
    //Asyngreeter = grpc::CreateChannel(server_address, std::move(grpc::InsecureChannelCredentials()));
    Asyngreeter = new GreeterAsynClient(grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials()));
    //处理业务，设置发送信息
    std::string user("world Asyn !!!");

    //业务逻辑，调用接口
    std::string reply = Asyngreeter->SayHello(user);  // The actual RPC call!
    std::cout << "Asyn Greeter received: " << reply << std::endl;

}

#if 1
void OSGI_API TestGRPCClient::TestgRPCAsynClient2Run(std::string server_address)
{
    //实例化客户端。
    //它需要一个通道，从中创建实际的RPC。
    //该通道为到端点（在本例中为端口50051处的localhost）的连接建模。
    //我们指示通道未通过身份验证（使用InsecureChannelCredentials())

    Asyngreeter2 = new GreeterAsynClient2(grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials()));

    // Spawn reader thread that loops indefinitely
    //生成无限循环的读取器线程,适合流场景
    //std::thread thread_ = std::thread(&GreeterAsynClient2::AsyncCompleteRpc, &Asyngreeter2);
    std::thread thread_ = std::thread(&GreeterAsynClient2::AsyncCompleteRpc, Asyngreeter2);

    for (int i = 0; i < 10; i++) {
      std::string user("world " + std::to_string(i));
      Asyngreeter2->SayHello(user);  // The actual RPC call!
    }

    std::cout << "Press control-c to quit" << std::endl << std::endl;
    thread_.join();  // blocks forever

}
#endif
